﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Globalization;
using Pixysoft.IO;
using Pixysoft.Framework.Logs.Core;
using Pixysoft.Framework.Configurations;

namespace Pixysoft.Framework.Logs.Controller
{
    /// <summary>
    /// 日志压缩打包与解压工具
    /// </summary>
    class LogPackageController
    {
        private static volatile LogPackageController instance;

        private static object syncRoot = new Object();

        public static LogPackageController Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        instance = new LogPackageController();
                    }
                }

                return instance;

            }
        }


        /// <summary>
        /// 指定日期之前的配置日志的文件数 不包含正在处理的文件
        /// </summary>
        /// <param name="log"></param>
        /// <param name="milliSecAgo"></param>
        /// <returns></returns>
        public int GetCountOfLogFiles(ILoggerSetting setting, int milliSecAgo)
        {
            return GetFiles(setting, milliSecAgo).Count;
        }

        private List<string> GetFiles(ILoggerSetting setting, int milliSecAgo)
        {
            List<string> list = new List<string>();

            DateTime time = Pixysoft.Tools.GlobalTimer.Instance.GetGlobalTime().AddMilliseconds(-1 * milliSecAgo);

            if (!Directory.Exists(setting.GetLogFilePath()))
                return list;

            foreach (string file in Directory.GetFiles(setting.GetLogFilePath()))
            {
                string filename = StringFilter.GetFileName(file);

                if (!filename.StartsWith(setting.Filename, StringComparison.OrdinalIgnoreCase))
                    continue;

                if (!filename.EndsWith(StringHelper.default_log_postfix, StringComparison.OrdinalIgnoreCase))
                    continue;

                if (filename.Equals(setting.Filename + StringHelper.default_log_postfix, StringComparison.OrdinalIgnoreCase))
                    continue;

                DateTime lasttime = DateTime.MinValue;

                if (!StringHelper.TryParseFileSequence(filename, out lasttime))
                    continue;

                if (lasttime > time)
                    continue;

                list.Add(file);
            }

            return list;
        }


        /// <summary>
        /// 指定日期之前的日志打包 包括正在处理的日志!! 2010-11-13
        /// </summary>
        /// <param name="log"></param>
        /// <param name="milliSecAgo"></param>
        /// <returns></returns>
        public ILogPackage Package(ILoggerSetting setting, int milliSecAgo)
        {
            LogPackage package = new LogPackage();

            LogDocument doc = new LogDocument(XmlManager.CreateNode(StringHelper.default_element_document));

            package.Document = doc;

            package.CreateDate = Pixysoft.Tools.GlobalTimer.Instance.GetGlobalTime();


            List<FileInfo> list = new List<FileInfo>();

            foreach (string file in GetFiles(package, setting, milliSecAgo))
            {
                list.Add(new FileInfo(file));
            }

            if (list.Count == 0)
                return package;

            string descfilename = setting.GetLogFilePath() + setting.Filename + "." + package.DateTo.ToString(StringHelper.default_log_pack_dateformat) +
                StringHelper.default_compress_postfix;

            Pixysoft.IO.GZipResult result = Pixysoft.IO.BatchCompressor.Compress(
                list.ToArray(), descfilename);

            //create document

            foreach (FileInfo info in list)
            {
                IXmlTree tree = GetXmlTree(info.FullName);

                foreach (IXmlNode node in tree.Node)
                {
                    ILogRecord record = doc.Records.Add(node);
                }
            }

            doc.Records.Sort();

            //delete

            foreach (FileInfo info in list)
            {
                info.Delete();
            }

            package.Destination = descfilename;

            return package;
        }

        private List<string> GetFiles(LogPackage package, ILoggerSetting setting, int milliSecAgo)
        {
            List<string> list = new List<string>();

            DateTime time = Pixysoft.Tools.GlobalTimer.Instance.GetGlobalTime().AddMilliseconds(-1 * milliSecAgo);

            if (!Directory.Exists(setting.GetLogFilePath()))
                return list;

            foreach (string file in Directory.GetFiles(setting.GetLogFilePath()))
            {
                string filename = StringFilter.GetFileName(file);

                if (!filename.StartsWith(setting.Filename, StringComparison.OrdinalIgnoreCase))
                    continue;

                if (!filename.EndsWith(StringHelper.default_log_postfix, StringComparison.OrdinalIgnoreCase))
                    continue;

                if (filename.Equals(setting.Filename + StringHelper.default_log_postfix, StringComparison.OrdinalIgnoreCase))
                {
                    list.Add(file);

                    continue;
                }

                DateTime lasttime = DateTime.MinValue;

                if (!StringHelper.TryParseFileSequence(filename, out lasttime))
                    continue;

                if (lasttime > time)
                    continue;

                if (package.DateFrom > lasttime)
                    package.DateFrom = lasttime;

                if (package.DateTo < lasttime)
                    package.DateTo = lasttime;

                list.Add(file);
            }

            package.Sources = list.ToArray();

            return list;
        }

        private IXmlTree GetXmlTree(string file)
        {
            IXmlCommand command = XmlManager.CreateCommand(file);

            command.Element = StringHelper.default_element_log;

            IXmlTree tree = command.ExecuteReader();

            return tree;
        }


        public string[] Unpackage(string zipFileFullName)
        {
            List<string> list = new List<string>();

            GZipResult result = Pixysoft.IO.BatchCompressor.Decompress(zipFileFullName);

            foreach (GZipFileInfo info in result.Files)
            {
                list.Add(info.LocalPath);
            }

            //File.Delete(zipFileFullName);

            return list.ToArray();
        }
    }
}
